package com.tracelog.core.model;

import com.tracelog.core.enums.IncludeType;
import com.tracelog.core.enums.LogLevel;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Duration;
import java.time.Instant;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 日志记录对象
 *
 * @author tracelog
 * @since 1.0.0
 */
@Data
@NoArgsConstructor
public class LogRecord {

    /**
     * 日志描述
     */
    private String description;

    /**
     * 所属模块
     */
    private String module;

    /**
     * 日志级别
     */
    private LogLevel level = LogLevel.INFO;

    /**
     * 请求信息
     */
    private RequestInfo request;

    /**
     * 响应信息
     */
    private ResponseInfo response;

    /**
     * 执行耗时
     */
    private Duration executionTime;

    /**
     * 开始时间
     */
    private Instant startTime;

    /**
     * 结束时间
     */
    private Instant endTime;

    /**
     * 异常信息
     */
    private String exceptionMessage;
    
    /**
     * 异常堆栈
     */
    private String exceptionStackTrace;

    /**
     * 请求者IP
     */
    private String clientIp;

    /**
     * 用户代理
     */
    private String userAgent;

    /**
     * 浏览器
     */
    private String browser;

    /**
     * 操作系统
     */
    private String operatingSystem;

    /**
     * 请求方法（GET、POST等）
     */
    private String method;

    /**
     * 请求URI
     */
    private String uri;

    /**
     * 类名
     */
    private String className;

    /**
     * 方法名
     */
    private String methodName;
    
    /**
     * 敏感字段列表
     */
    private Set<String> sensitiveFields = new HashSet<>();
    
    /**
     * 创建日志记录
     *
     * @param startTime 开始时间
     * @param includes  包含信息
     * @return 日志记录
     */
    public static LogRecord create(Instant startTime, Set<IncludeType> includes) {
        LogRecord logRecord = new LogRecord();
        logRecord.setStartTime(startTime);
        
        if (includes.contains(IncludeType.REQUEST_BODY) || 
            includes.contains(IncludeType.REQUEST_PARAM) || 
            includes.contains(IncludeType.REQUEST_HEADERS)) {
            logRecord.setRequest(new RequestInfo());
        }
        
        if (includes.contains(IncludeType.RESPONSE_BODY) || 
            includes.contains(IncludeType.RESPONSE_HEADERS)) {
            logRecord.setResponse(new ResponseInfo());
        }
        
        return logRecord;
    }

    /**
     * 完成日志记录
     *
     * @param endTime 结束时间
     */
    public void complete(Instant endTime) {
        this.endTime = endTime;
        this.executionTime = Duration.between(this.startTime, endTime);
    }

    /**
     * 请求信息
     */
    @Data
    public static class RequestInfo {
        /**
         * 请求头
         */
        private Map<String, String> headers;

        /**
         * 请求体
         */
        private Object body;

        /**
         * 请求参数
         */
        private Map<String, String[]> parameters;
    }

    /**
     * 响应信息
     */
    @Data
    public static class ResponseInfo {
        /**
         * 响应头
         */
        private Map<String, String> headers;

        /**
         * 响应体
         */
        private Object body;

        /**
         * 状态码
         */
        private int status;
    }
} 